package org.jeecg.modules.api.geo.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.jeecg.common.exception.JeecgBootException;
import org.jeecg.modules.api.geo.service.IBimApiGeoService;
import org.jeecg.modules.core.constant.YesOrNotEnum;
import org.jeecg.modules.geo.core.constant.BimGeoApiTypeConstant;
import org.jeecg.modules.geo.entity.BimGeoApi;
import org.jeecg.modules.geo.entity.BimGeoApp;
import org.jeecg.modules.geo.model.dto.GeoDTO;
import org.jeecg.modules.geo.model.param.GeoAreaParam;
import org.jeecg.modules.geo.model.vo.GeoVO;
import org.jeecg.modules.geo.model.vo.PointCloudVO;
import org.jeecg.modules.geo.service.IBimGeoApiService;
import org.jeecg.modules.geo.service.IBimGeoAppAuthService;
import org.jeecg.modules.geo.service.IBimGeoAppService;
import org.jeecg.modules.geo.service.resolve.IGeoResolve;
import org.jeecg.modules.project.entity.ProjectInfo;
import org.jeecg.modules.project.service.IProjectInfoService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.nio.charset.Charset;
import java.util.*;

@Service
@Slf4j
public class BimApiGeoServiceImpl implements IBimApiGeoService {

    @Autowired
    private IBimGeoAppService bimGeoAppService;

    @Autowired
    private IBimGeoApiService bimGeoApiService;

    @Autowired
    private IBimGeoAppAuthService bimGeoAppAuthService;

    @Autowired
    private IProjectInfoService projectInfoService;

    @Autowired
    private IGeoResolve geoResolve;

    @Override
    public GeoVO getGeoInfo(Long projectId, String appCode, HttpServletRequest httpServletRequest) {
        //查询对应项目绑定的api
        ProjectInfo queryProj = new ProjectInfo();
        queryProj.setProjectId(projectId);
        if(StringUtils.isNotBlank(appCode)){
            queryProj.setAppCode(appCode);
        }
        ProjectInfo projectInfo = projectInfoService.findByProj(queryProj);
        if (projectInfo == null) {
            throw new JeecgBootException("找不到相关工程！");
        }
        // 应用信息
        BimGeoApp bimGeoApp = bimGeoAppService.find(BimGeoApp::getAppCode, appCode);
        if (bimGeoApp == null) {
            throw new JeecgBootException("找不到相关应用！");
        }
        // 接口信息
        if(StringUtils.isBlank(projectInfo.getApiId())){
            throw new JeecgBootException("未配置模型业务数据api！");
        }
        GeoVO geoVO = new GeoVO();
        List<String> apiList = Arrays.asList(projectInfo.getApiId().split(","));
        for(String apiId : apiList) {
            List<BimGeoApi> bimGeoApis = bimGeoApiService.geoApiByApp(null, Integer.valueOf(apiId));
            if (CollUtil.isEmpty(bimGeoApis)) {
                throw new JeecgBootException("找不到相关Api！");
            }
            //获取token
            String token = bimGeoAppAuthService.auth(bimGeoApp.getId());
            if (StrUtil.isBlank(token)) {
                throw new JeecgBootException("获取业务系统数据鉴权失败");
            }
            //获取请求参数
            Map<String, String> paramMap = HttpUtil.decodeParamMap(httpServletRequest.getQueryString(), Charset.defaultCharset());
            //构建请求
            HttpRequest request = bimGeoApiService.getRequest(bimGeoApp, bimGeoApis.get(0), paramMap);
            // api请求
            HttpResponse response = request.execute();
            String body = response.body();
            if (StrUtil.isEmpty(body)) {
                throw new JeecgBootException("获取业务系统数据为空");
            }
            String geoData = JSON.parseObject(body).getString("data");
            if (StrUtil.isEmpty(geoData)) {
                throw new JeecgBootException("获取业务系统数据为空");
            }
            GeoDTO geoDTO = JSON.parseObject(geoData, GeoDTO.class);
            if (geoDTO != null) {
                //构建数据格式
                GeoVO resolve = geoResolve.resolve(geoDTO, projectId);
                List<PointCloudVO> pointCloud = resolve.getPointCloud();
                if (CollUtil.isNotEmpty(pointCloud)) {
                    pointCloud.forEach(item -> {
                        StringBuilder stringBuilder = new StringBuilder("&token=");
                        stringBuilder.append(token);
                        if (StrUtil.isNotBlank(item.getPublicQuery())) {
                            stringBuilder.append("&");
                            stringBuilder.append(item.getPublicQuery());
                        }
                        item.setPublicQuery(stringBuilder.toString());
                    });
                }
                if (BeanUtil.isEmpty(geoVO)) {
                    BeanUtil.copyProperties(resolve, geoVO);
                } else {
                    geoVO.getDevs().addAll(resolve.getDevs());
                    geoVO.getAreas().addAll(resolve.getAreas());
                    geoVO.getPointCloud().addAll(resolve.getPointCloud());
                }
            }
        }
        return geoVO;
    }

    @Override
    public void addGeoInfo(GeoAreaParam geoAreaParam, HttpServletRequest httpServletRequest) {
        BimGeoApp bimGeoApp = bimGeoAppService.find(BimGeoApp::getAppCode, geoAreaParam.getAppCode());
        if (bimGeoApp == null) {
            throw new JeecgBootException("查不到响应的应用信息");
        }
        BimGeoApi bimGeoApi = bimGeoApiService.find(bimGeoApp.getId(), BimGeoApiTypeConstant.DATA_UPLOAD_TYPE.getValue(), 1);
        List<Object> geoAreaDTOs = geoAreaParam.getArea();
        List<Object> requestParams = new ArrayList<>();
        for (Object areaDTO : geoAreaDTOs) {
            Map<String, Object> areaMap = BeanUtil.beanToMap(areaDTO);
            Map<String, Object> base = BeanUtil.beanToMap(areaMap.get("base"));
            base.put("projectId", geoAreaParam.getProjectId());
            requestParams.add(areaDTO);
        }
        HttpRequest request = bimGeoApiService.getRequest(bimGeoApi.getAppId(), requestParams);
        request.execute();
    }

    @Override
    public String queryProjectForApiId(Integer projectApiId, HttpServletRequest httpServletRequest) {
        //对应api接口
        BimGeoApi geoApi = bimGeoApiService.lambdaQuery(). eq(projectApiId != null, BimGeoApi::getId, projectApiId)
                .eq(BimGeoApi::getEnableFlag, YesOrNotEnum.Y.getCode())
                .list().stream().findFirst().orElse(null);
        if (Objects.isNull(geoApi)) {
            throw new JeecgBootException("未查询到对应的配置应用接口配置信息");
        }
        //查询配置的应用
        BimGeoApp bimGeoApp = bimGeoAppService.getById(geoApi.getAppId());
        if (Objects.isNull(bimGeoApp)) {
            throw new JeecgBootException("未查询到对应的配置应用");
        }
        Map<String, String> queryMap = HttpUtil.decodeParamMap(httpServletRequest.getQueryString(), Charset.defaultCharset());
        HttpRequest request = bimGeoApiService.getRequest(bimGeoApp, geoApi, queryMap);
        String body = request.execute().body();
        log.info("获取第三方应用项目列表请求参数=>{},响应=>{}", JSON.toJSONString(queryMap), body);
        return body;
    }

    @Override
    public String queryApi(String businessType, HttpServletRequest httpServletRequest) {
        //对应api接口
        BimGeoApi geoApi = bimGeoApiService.lambdaQuery(). eq(BimGeoApi::getBusinessType, businessType)
                .eq(BimGeoApi::getEnableFlag, YesOrNotEnum.Y.getCode())
                .list().stream().findFirst().orElse(null);
        if (Objects.isNull(geoApi)) {
            throw new JeecgBootException("未查询到对应的配置应用接口配置信息");
        }
        Map<String, String> queryMap = HttpUtil.decodeParamMap(httpServletRequest.getQueryString(), Charset.defaultCharset());
        //获取对应api的请求
        HttpRequest request = bimGeoApiService.getRequest(geoApi.getId(), queryMap);
        String body = request.execute().body();
        log.info("查询apiId=>{},参数=>{},响应=>{}", geoApi.getAppId(), queryMap, body);
        return body;
    }
}
